package com.xique.park.controller.client.web.service.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xique.common.core.constant.Constants;
import com.xique.common.core.constant.UserConstants;
import com.xique.common.core.domain.R;
import com.xique.common.core.utils.*;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.common.security.service.TokenService;
import com.xique.park.bean.domain.ParkConfig;
import com.xique.park.bean.domain.ParkLane;
import com.xique.park.bean.domain.ParkOn;
import com.xique.park.bean.domain.client.ClientLaneConfig;
import com.xique.park.bean.request.client.ClientCancelPassRequest;
import com.xique.park.bean.request.client.ClientSpaceEditRequest;
import com.xique.park.bean.request.comm.ParkOnEditPlateSaveRequest;
import com.xique.park.bean.vo.client.ClientLaneVo;
import com.xique.park.controller.client.web.api.ClientServiceName;
import com.xique.park.controller.client.web.api.IClientApi;
import com.xique.park.controller.client.web.api.IClientPassApi;
import com.xique.park.controller.client.web.bean.domain.Client;
import com.xique.park.controller.client.web.bean.domain.ClientUser;
import com.xique.park.controller.client.web.bean.domain.SysUser;
import com.xique.park.controller.client.web.bean.request.*;
import com.xique.park.controller.client.web.bean.vo.ClientHandOutParkInInfoVo;
import com.xique.park.controller.client.web.bean.vo.ClientListVO;
import com.xique.park.controller.client.web.enums.ClientErrorEnums;
import com.xique.park.controller.client.web.service.biz.service.IClientCommandService;
import com.xique.park.controller.client.web.service.biz.service.IClientHomeBizService;
import com.xique.park.controller.client.web.service.biz.service.IClientLoginInfoBizService;
import com.xique.park.controller.client.web.service.service.IClientService;
import com.xique.park.controller.client.web.service.service.IClientUserService;
import com.xique.park.controller.client.web.service.service.ISysUserService;
import com.xique.park.mapper.ParkOnMapper;
import com.xique.park.service.biz.service.IParkOnBizService;
import com.xique.park.service.service.*;
import com.xique.system.api.RemoteSystemDictService;
import com.xique.system.api.RemoteSystemLogService;
import com.xique.system.api.dto.SystemDictDataDTO;
import com.xique.system.api.model.LoginSystemUser;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.beans.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author shd
 * @create 2021/7/22 15:54
 */
@Service
@Slf4j
public class ClientHomeBizServiceImpl implements IClientHomeBizService {

    @Autowired
    private IClientService clientService;

    @Autowired
    private IClientUserService clientUserService;

    @Autowired
    private IClientApi clientApi;

    @Autowired
    private IClientLoginInfoBizService clientLoginInfoBizService;

    @Autowired
    private ParkOnMapper parkOnMapper;

    @Autowired
    private IParkOnService parkOnService;

    @Autowired
    private IClientPassApi clientPassApi;

    @Autowired
    private AliossUtil aliossUtil;

    @Autowired
    private RemoteSystemDictService remoteSystemDictService;

    @Autowired
    private RemoteSystemDictService dictService;

    @Autowired
    private IClientLaneConfigService clientLaneConfigService;

    @Autowired
    private IParkLaneService parkLaneService;

    @Autowired
    private IClientCommandService clientCommandService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RemoteSystemLogService remoteSystemLogService;

    @Autowired
    private IParkConfigService parkConfigService;

    @Autowired
    private IParkOnBizService parkOnBizService;

    /**
     * 岗亭列表
     * @author shd
     * @date 2021/7/23 9:50
     * @return com.xique.common.core.web.domain.AjaxResult
     */
    @Override
    public AjaxResult getClientList(Long userId) {

        ClientUser clientUser = new ClientUser();
        clientUser.setSysUserId(userId);
        List<ClientUser> clientUserList = clientUserService.selectClientUserList(clientUser);
        List<Long> clientIds = clientUserList.stream().map(ClientUser::getClientId).distinct().collect(Collectors.toList());

        List<Client> clientList = clientService.selectClientByIds(clientIds);
        List<ClientListVO> vos = OrikaUtil.converts(clientList, ClientListVO.class);

        Map<String, Object> map = new HashMap<>(1);
        map.put("list", vos);

        return AjaxResult.success(map);
    }

    /**
     * 选择岗亭
     * @author shd
     * @date 2021/7/23 9:50
     * @return com.xique.common.core.web.domain.AjaxResult
     */
    @Override
    public AjaxResult selectClient(ClientHomeSelectClientRequest request) {

        Long userId = SecurityUtils.getUserId();
        Long clientId = request.getClientId();

        // 删除原登录用户信息
        Client client = clientService.selectClientById(clientId);
        if (null != client.getSysUserId()) {
            ClientUser search = new ClientUser();
            search.setSysUserId(client.getSysUserId());
            search.setClientId(clientId);
            ClientUser clientUser = clientUserService.selectOne(search);
            if (null != clientUser) {
                tokenService.delLoginUser(clientUser.getToken());
                // 添加登出日志
                clientLoginInfoBizService.addLoginInfo(clientId, client.getLoginUserName(), Constants.LOGOUT, "退出成功");
                remoteSystemLogService.saveLoginInfo(client.getLoginUserName(), Constants.LOGOUT, "退出成功", UserConstants.Platform.CLIENT);
            }
        }

        // 更新岗亭表内的登录信息
        SysUser sysUser = sysUserService.getById(userId);
        Client update = new Client();
        update.setId(clientId);
        update.setSysUserId(userId);
        update.setLoginUserName(sysUser.getLoginName());
        update.setLoginTime(DateUtils.getNowDate());

        int count = clientService.updateClient(update);

        if (count <= 0) {
            return new AjaxResult(ClientErrorEnums.SELECT_CLIENT_FAIL);
        }

        ClientUser updateClientUser = new ClientUser();
        updateClientUser.setSysUserId(userId);
        updateClientUser.setClientId(clientId);
        updateClientUser.setToken(SecurityUtils.getToken());

        clientUserService.updateClientUser(updateClientUser);

        LoginSystemUser loginClientUser = tokenService.getLoginUser();
        loginClientUser.setClientId(clientId);
        tokenService.refreshToken(loginClientUser);

        clientLoginInfoBizService.addLoginInfo(clientId, sysUser.getLoginName(), Constants.LOGIN_SUCCESS, "登录成功");

        return new AjaxResult(ClientErrorEnums.SELECT_CLIENT_SUCCESS);
    }

    /**
     * 获取岗亭首页信息
     * @author shd
     * @date 2021/7/27 10:50
     * @return com.xique.common.core.web.domain.AjaxResult
     */
    @Override
    public AjaxResult getHomePageInfo(String clientId) {
        return new AjaxResult(clientApi.getHomePageInfo(clientId));
    }

    /**
     * 获取岗亭设备列表
     * @author shd
     * @date 2021/7/29 10:24
     * @return com.xique.common.core.web.domain.AjaxResult
     */
    @Override
    public AjaxResult getDeviceList(ClientDeviceListRequest request) {
        return null;
    }

    @Override
    public AjaxResult editClientLaneConfig(WebClientLaneConfig request) {
        request.setClientId(SecurityUtils.getClientId());
        ClientLaneConfig laneConfig = OrikaUtil.convert(request, ClientLaneConfig.class);
        int count = clientLaneConfigService.updateClientLaneFunction(laneConfig);
        if (count <= 0) {
            return AjaxResult.error("编辑失败");
        }
        return AjaxResult.success("成功");
    }

    @Override
    public AjaxResult lanDetail(Long laneId) {
        ClientLaneConfig clientLaneConfig = new ClientLaneConfig();
        clientLaneConfig.setClientId(SecurityUtils.getClientId());
        clientLaneConfig.setLaneId(laneId);
        List<ClientLaneConfig> clientLaneConfigs = clientLaneConfigService.selectClientLaneConfigList(clientLaneConfig);
        if (clientLaneConfigs.isEmpty()){
            return AjaxResult.error();
        }
        ParkLane parkLane = parkLaneService.selectParkLaneById(laneId);
        ClientLaneVo laneVo = new ClientLaneVo();
        laneVo.setId(parkLane.getId().toString());
        laneVo.setName(parkLane.getName());
        laneVo.setLaneType(parkLane.getLaneType());
        laneVo.setLaneTypeLabel(parkLane.getLaneTypeLabel());
        laneVo.setModel(parkLane.getModel());
        laneVo.setModelLabel(parkLane.getModelLabel());
        laneVo.setConfig(JSON.parseObject(clientLaneConfigs.get(0).getConfig()));

        return AjaxResult.success(laneVo);
    }

    @Override
    public AjaxResult handCarInOrOut(WebClientHandInOutRequest request) {
        ParkOn parkOn = new ParkOn();
        parkOn.setPlate(request.getPlate());
        parkOn.setInTime(DateUtils.parseDate(request.getInTime()));
        parkOn.setParkId(SecurityUtils.getParkId());
        parkOn.setPlateType(request.getPlateType());
        return clientCommandService.markCarInOrOut(SecurityUtils.getParkId(), request.getSn(), request.getIsGate(), parkOn);
    }

    @Override
    public AjaxResult editParkOnPlate(ParkOnEditPlateSaveRequest request) {
        return parkOnBizService.editPlateInfo(request);
    }

    @Override
    public AjaxResult getParkOnUrl(String recordId) {
        ParkOn parkOn = parkOnService.selectParkOnById(Long.valueOf(recordId));
        String objectName = parkOn.getInPic();
        if(null != objectName && !"null".equals(objectName) && StringUtils.isNotEmpty(objectName)){
            URL url = aliossUtil.getJzyGetObjectUrl(objectName);
            return AjaxResult.success("图片访问路径",url.toString());
        }else{
            return AjaxResult.success("无图片","[表情]_pic.png");
        }
    }

    @Override
    public AjaxResult getHandOutInfo(WebClientHandInOutRequest request) {
        return null;
    }

    @Override
    public AjaxResult cancelPass(ClientCancelPassRequest request) {
        return null;
    }

    @Override
    public AjaxResult cashPass(ClientCashOrFreePassRequest request) {
        Long parkId = SecurityUtils.getParkId();
        Long clientId = SecurityUtils.getClientId();
        request.setService(ClientServiceName.CLIENTCASHPASS);
        request.setVersion("1.0");
        JSONObject data = new JSONObject();

        data.put("parkId",parkId);
        data.put("plate",request.getPlate());
        data.put("gateId",request.getLaneId());
        double fee = Double.parseDouble(request.getFee()) * 100;
//        data.put("fee", fee);
        data.put("fee", new Double(fee).longValue());
        double totalFee = Double.parseDouble(request.getTotalFee()!=null?request.getTotalFee():"0") * 100;
//        data.put("totalFee", totalFee);
        data.put("totalFee", new Double(totalFee).longValue());
        double couponFee = Double.parseDouble(request.getCoupon()!=null?request.getCoupon():"0") * 100;
//        data.put("coupon", couponFee);
        data.put("coupon", new Double(couponFee).longValue());
        ParkOn parkOn = new ParkOn();
        parkOn.setParkId(parkId);
        parkOn.setPlate(request.getPlate());
        List<ParkOn> parkOns = parkOnMapper.selectParkOnBaseList(parkOn);
        if (parkOns.isEmpty()){
            WebClientHandInOutRequest clientHandInOutRequest = new WebClientHandInOutRequest();
            clientHandInOutRequest.setPlate(request.getPlate());
            clientHandInOutRequest.setInTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,request.getOutTime()));
            clientHandInOutRequest.setSn(request.getDeviceCode());
            AjaxResult result = this.handCarInOrOut(clientHandInOutRequest);
            log.info("岗亭确认放行-在场记录未匹配到，手动出场命令已下发" + result);
            return AjaxResult.success("在场记录未匹配到，手动出场命令已下发");
        }
        data.put("parkingSerial",parkOns.get(0).getParkingSerial());
        data.put("updateUser",SecurityUtils.getUserId());
        data.put("clientId",SecurityUtils.getClientId());
        data.put("clientUserId",SecurityUtils.getUserId());
        request.setData(data);
        BeanMap map = BeanMap.create(request);
        JSONObject result = clientPassApi.pass(map);
        String message = (String) result.get("message");
        Integer resultCode = (Integer) result.get("result_code");

        if (StringUtils.isNull(clientId)) {
            return 0 == resultCode ? AjaxResult.success(message) : AjaxResult.error(message);
        }

        Client client = clientService.selectClientById(clientId);
        double sumCash = clientService.sumClientCash(client.getLoginTime(), String.valueOf(client.getLoginUserId()), String.valueOf(clientId));
        Map<String, Object> dt = new HashMap<>();
        dt.put("sumCash",sumCash/100);
        return resultCode == 0 ? AjaxResult.success(message,dt) : AjaxResult.error(message);
    }

    @Override
    public AjaxResult freePass(ClientCashOrFreePassRequest request) {
        Long parkId = SecurityUtils.getParkId();
        request.setService(ClientServiceName.CLIENTFREEPASS);
        request.setVersion("1.0");
        JSONObject data = new JSONObject();
        data.put("parkId",parkId);
        data.put("plate",request.getPlate());
        data.put("gateId",request.getLaneId());
        double fee = Double.parseDouble(request.getFee()) * 100;
//        data.put("fee", fee);
        data.put("fee", new Double(fee).longValue());
        data.put("updateUser",SecurityUtils.getUserId());
        data.put("clientId",SecurityUtils.getClientId());
        ParkOn parkOn = new ParkOn();
        parkOn.setParkId(parkId);
        parkOn.setPlate(request.getPlate());
        List<ParkOn> parkOns = parkOnMapper.selectParkOnBaseList(parkOn);
        if (parkOns.isEmpty()){
            WebClientHandInOutRequest clientHandInOutRequest = new WebClientHandInOutRequest();
            clientHandInOutRequest.setPlate(request.getPlate());
            clientHandInOutRequest.setInTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,request.getOutTime()));
            clientHandInOutRequest.setSn(request.getDeviceCode());
            AjaxResult result = this.handCarInOrOut(clientHandInOutRequest);
            log.info("岗亭确认放行-在场记录未匹配到，手动出场命令已下发" + result);
            return AjaxResult.success("在场记录未匹配到，手动出场命令已下发");
        }
        data.put("parkingSerial",parkOns.get(0).getParkingSerial());
        request.setData(data);
        BeanMap map = BeanMap.create(request);
        JSONObject result = clientPassApi.pass(map);
        String message = (String) result.get("message");
        Integer resultCode = (Integer) result.get("result_code");

        return resultCode == 0 ? AjaxResult.success(message) : AjaxResult.error(message);
    }

    @Override
    public AjaxResult getSpaceInfo() {
        JSONObject object = clientPassApi.space(SecurityUtils.getParkId());
        AjaxResult result = new AjaxResult(Integer.parseInt(object.get("code").toString()), object.get("msg").toString(), object.get("data"));
        return new AjaxResult(result);
    }

    @Override
    public AjaxResult spaceEdit(ClientSpaceEditRequest request) {
        return null;
    }

    @Override
    public AjaxResult getLaneInfo(Long deviceId) {
        return null;
    }

    @Override
    public AjaxResult cashPassList(WebClientCashPassListRequest request) {
        return null;
    }

    @Override
    public AjaxResult parkInDetail(Long inId) {
        return null;
    }

    @Override
    public AjaxResult selectParkOutDetail(Long outId) {
        return null;
    }

    @Override
    public AjaxResult confirmIn(ClientConfirmInRequest request) {
        request.setUpdateUser(SecurityUtils.getUserId());
        request.setParkId(SecurityUtils.getParkId());
        BeanMap map = BeanMap.create(request);
        JSONObject object = clientPassApi.confirmIn(map);
        AjaxResult result = new AjaxResult(Integer.parseInt(object.get("code").toString()), object.get("msg").toString());
        return new AjaxResult(result);
    }

    @Override
    public AjaxResult getHandOutParkOnList(HandOutParkOnListRequest request) {
        Map<String, Object> map = new HashMap<>();
        ParkOn parkOn = new ParkOn();
        parkOn.setParkId(SecurityUtils.getParkId());
        parkOn.setPlate(request.getPlate());
        List<ClientHandOutParkInInfoVo> list = parkOnService.getHandOutParkInInfoVoList(parkOn);
        if(CollectionUtils.isNotEmpty(list)){
            list.forEach(item -> {
                item.setInPic(StringUtils.isNotEmpty(item.getInPic()) ? aliossUtil.getJzyGetObjectUrl(item.getInPic()).toString() : "");
                String inStatus = item.getInStatus();
                if(StringUtils.isNotEmpty(inStatus)){
                    item.setInStatus(dictService.getDictLabel("car_pass_status",inStatus).getData());
                }
            });
        }
        map.put("list",list);
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult isAllowEditInTime() {
        Map<String,Object> map = new HashMap<>();
        if(null != SecurityUtils.getParkId()){
            ParkConfig parkConfig = parkConfigService.selectParkConfigByParkId(SecurityUtils.getParkId());
            if(parkConfig != null && StringUtils.isNotEmpty(parkConfig.getConfig())){
                JSONObject configObj = JSON.parseObject(parkConfig.getConfig());
                map.put("isAllowEditInTime",null != configObj.getString("isAllowEditInTime") ? configObj.getString("isAllowEditInTime") : "N");
            }else{
                map.put("isAllowEditInTime","N");
            }
            return AjaxResult.success(map);
        }else{
            return AjaxResult.error("车场参数不能为空");
        }
    }

    @Override
    public AjaxResult getFreePassReason() {
        R<List<SystemDictDataDTO>> res = remoteSystemDictService.getDictDataByType("reason_free_pass");
        if(null != res){
            Map<String,Object> map = new HashMap<>();
            map.put("list",res.getData());
            return AjaxResult.success(map);
        }else{
            return AjaxResult.error("请联系管理员在后台录入免费放行原因");
        }
    }

    @Override
    public AjaxResult getOpenGateReason() {
        R<List<SystemDictDataDTO>> res = remoteSystemDictService.getDictDataByType("reason_open_gate");
        if(null != res){
            Map<String,Object> map = new HashMap<>();
            map.put("list",res.getData());
            return AjaxResult.success(map);
        }else{
            return AjaxResult.error("请联系管理员在后台录入开闸原因");
        }
    }

    @Override
    public AjaxResult getCloseGateReason() {
        R<List<SystemDictDataDTO>> res = remoteSystemDictService.getDictDataByType("reason_close_gate");
        if(null != res){
            Map<String,Object> map = new HashMap<>();
            map.put("list",res.getData());
            return AjaxResult.success(map);
        }else{
            return AjaxResult.error("请联系管理员在后台录入关闸原因");
        }
    }
}
